﻿using System;
using System.Collections.Generic;
using UnityEngine;
using XLua;

namespace Yunchang.ILUI
{
    [LuaCallCSharp]
    [Hotfix]
    public class UILayer
    {
        public enum Type
        {
            HeadBoard = 1,
            MainUI,
            Ordinary,
            BottomRemind,
            Tips,
            TopDialog,
            Announcement,
            TopRemind,
            TalkUI,
            loading,
            Top,
            Max
        }

        /// <summary>
        /// 供外部访问的变换对象 
        /// </summary>
        public RectTransform transform { get; set; }

        /// <summary>
        /// UI组的互斥控制根节点，transform的子节点,所有UI面板都放在这一级下边。无特殊需求外部类禁止访问
        /// </summary>
        public RectTransform uiStackTransform { get; private set; }

        /// <summary>
        /// 本层上层层组里有对下层互斥的层组
        /// </summary>
        public bool UpLayerHasMutex { get; private set; }

        /// <summary>
        /// 本组的索引值
        /// </summary>
        public int index { get; private set; }

        /// <summary>
        /// 本组起始Depth
        /// </summary>
        public int StartPanelDepth { get; private set; }

        /// <summary>
        /// 当前组内有对下级隐藏的UIBase
        /// </summary>
        public bool HasPile { get; private set; }

        /// <summary>
        /// 组数据配置
        /// </summary>
        public TableUILayer table { get; private set; }

        /// <summary>
        /// 本组内UI列表
        /// </summary>
        private List<UIPage> StackList = new List<UIPage>();

        /// <summary>
        /// 本组是否被激活
        /// </summary>
        public bool Active
        {
            get { return uiStackTransform.gameObject.activeSelf; }
        }

        public UILayer(int index, int startPanelDepth, TableUILayer table, RectTransform transform)
        {
            this.index = index;
            this.table = table;
            this.transform = transform;
            this.uiStackTransform =
                UIPageManager.CreatRectTransform(this.transform, "UIlist"); //new GameObject("UIList").transform;
            /* this.uiStackTransform.parent = this.transform;
             this.uiStackTransform.localPosition = Vector3.zero;
             this.uiStackTransform.localScale = Vector3.one;*/
            this.StartPanelDepth = startPanelDepth;
            UpLayerHasMutex = false;
            HasPile = false;

            this.transform.gameObject.SetActive(false);
        }

        public int PageCount
        {
            get { return StackList.Count; }
        }

        public bool HasUIOpen
        {
            get
            {
                if (!uiStackTransform.gameObject.activeInHierarchy) return false;
                for (int i = 0; i < StackList.Count; i++)
                {
                    if (StackList[i].activeSelf)
                        return true;
                }

                return false;
            }
        }


        /// <summary>
        /// 供外部调用显示隐藏的接口，因此为上层节点所以优先级高于互斥隐藏
        /// </summary>
        /// <param name="active"></param>
        public void SetActive(bool active)
        {
            if (this.Active != active)
            {
                uiStackTransform.gameObject.SetActive(active);
            }
        }


        public UIPage GetUIPage(string name)
        {
            int count = StackList.Count;
            UIPage tmpUI;
            for (int i = 0; i < count; i++)
            {
                tmpUI = StackList[i];
                if (tmpUI != null && tmpUI.ID == name)
                {
                    return tmpUI;
                }
            }

            return null;
        }

        /// <summary>
        /// 清除本组内所有UI面板
        /// </summary>
        public void Clear()
        {
            while (StackList.Count > 0)
            {
                UIPage ui = StackList[0];
                StackList.RemoveAt(0);
                if (ui != null)
                    ui.Close();
            }

            HasPile = false;
            SetActive(true);
            UpLayerHasMutex = false;
            if (!uiStackTransform.gameObject.activeSelf)
                uiStackTransform.gameObject.SetActive(true);
        }

        /// <summary>
        /// 添加UI面板
        /// </summary>
        /// <param name="ui"></param>
        public void PushUIPage(UIPage ui)
        {
            if (StackList.Contains(ui))
                return;
            PushStack(ui);

            if (StackList.Count > 0 && !this.transform.gameObject.activeSelf)
                this.transform.gameObject.SetActive(true);
        }

        /// <summary>
        /// 将组内某面板置顶
        /// </summary>
        /// <param name="id"> </param>
        public void SetToTop(string name)
        {
            int count = StackList.Count;
            for (int i = 0; i < count; i++)
            {
                if (StackList[i].ID == name)
                {
                    UIPage ui = StackList[i];
                    StackList.RemoveAt(i);
                    StackList.Add(ui);

                    for (int k = i; k < count; k++)
                    {
                        StackList[k].SetStackIndex(k, true);
                    }

                    return;
                }
            }
        }


        /// <summary>
        /// 移除UI面板 
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool RemoveUIPage(string id)
        {
            UIPage ui = null;
            UIPage tmp = null;

            bool change = false;
            bool indexSort = false;
            for (int i = 0; i < StackList.Count;)
            {
                tmp = StackList[i];

                if (tmp == null)
                {
                    StackList.RemoveAt(i);
                    indexSort = true;
                    continue;
                }

                if (tmp.ID == id)
                {
                    ui = tmp;
                    StackList.RemoveAt(i);
                    change = true;
                    indexSort = true;
                    continue;
                }

                //有移除的话，要更新上层的depth
                if (indexSort)
                {
                    StackList[i].SetStackIndex(i, false);
                }

                i++;
            }

            if (change) UpStack();


            if (StackList.Count < 1)
                this.transform.gameObject.SetActive(false);
            return ui != null;
        }

        /// <summary>
        /// 叠加UI面板
        /// </summary>
        /// <param name="ui"></param>
        private void PushStack(UIPage ui)
        {
            StackList.Add(ui);
            int count = StackList.Count;
            ui.SetStackIndex(count - 1, false);

            if (UpLayerHasMutex)
            {
                ui.SetActive(false);
                return;
            }

            if (ui.table.pileType == 1)
            {
                HasPile = true;

                //组互斥
                if (index > 0 && index < UIPageManager.Ins.LayerArray.Length)
                {
                    GLog.Log("===PushStack group mutex = {0} :{1} ", table.name, ui.ID);
                    UILayer layer;
                    for (int i = index - 1; i >= 0; i--)
                    {
                        layer = UIPageManager.Ins.LayerArray[i];
                        layer.UpLayerHasMutex = true;

                        if (layer.table.mutexed == 1) //是否本组可以被互斥
                        {
                            if (layer.uiStackTransform.gameObject.activeSelf)
                                layer.uiStackTransform.gameObject.SetActive(false);
                        }

                        //  layer.SetLayerMutex(true);
                        if (layer.HasPile) break;
                    }
                }

                //组内互斥 
                if (table.autoPileSort == 1)
                {
                    SetMutexed(ui, count - 2);
                }
            }
        }

        /// <summary>
        /// 设置组内UI互斥被隐藏或关闭
        /// </summary>
        /// <param name="lastIndex"></param>
        private void SetMutexed(UIPage target, int lastIndex)
        {
            UIPage tmpUI;
            int removeIndex = -1;
            for (int i = lastIndex; i >= 0; i--)
            {
                //这个地方要做个判断，因为在互斥关闭的过程中可能引起连锁反应，导致当前这个界面被关闭了。
                if (!target.activeSelf)
                {
                    GLog.Log("SetMutexed but tartget UI active is false! targetUI.id={0} ", target.ID);
                    break;
                }

                tmpUI = StackList[i];
                if (tmpUI != null)
                {
                    if (tmpUI.table.pileMutexed == 0) //0直接关闭
                    {
                        StackList.RemoveAt(i);
                        UIPageManager.Ins.ClosePage(tmpUI.ID, false);
                        removeIndex = i;
                    }
                    else if (tmpUI.table.pileMutexed == 1) //1隐藏
                    {
                        tmpUI.SetActive(false);
                    }

                    if (tmpUI.table.pileType == 1) break;
                }
            }

            //有移除需要更新depth
            if (removeIndex >= 0)
            {
                int count = StackList.Count;
                for (int i = removeIndex; i < count; i++)
                {
                    if (StackList[i] != null)
                        StackList[i].SetStackIndex(i, false);
                }

                //  UIPanel.list.Sort(UIPanel.CompareFunc);
            }
        }

        /// <summary>
        /// 释放本组互斥 ,返回是否本组还有对下层互斥的UI
        /// </summary>
        /// <param name="lastIndex"></param>
        /// <returns></returns>
        private bool ReleaseMutexed(int lastIndex)
        {
            bool HasPile = false;
            UIPage tmpUI;
            for (int i = lastIndex; i >= 0; i--)
            {
                tmpUI = StackList[i];
                if (tmpUI != null)
                {
                    tmpUI.SetActive(true);
                    if (tmpUI.table.pileType == 1)
                    {
                        HasPile = true;
                        break;
                    }
                }
            }

            return HasPile;
        }

        /// <summary>
        /// 移除释放堆叠
        /// </summary>
        private void UpStack()
        {
            if (UpLayerHasMutex) return;

            int count = StackList.Count;
            UIPage tmpUI = null;

            //得到本组最上边的UI
            for (int i = count - 1; i >= 0; i--)
            {
                tmpUI = StackList[i];
                if (tmpUI == null)
                {
                    StackList.RemoveAt(i);
                }
                else break;
            }

            HasPile = false; //本组是否还有UI对下层互斥
            if (tmpUI != null)
            {
                tmpUI.SetActive(true);
                HasPile = tmpUI.table.pileType == 1;
                //组内互斥释放
                if (!HasPile)
                {
                    count = StackList.Count;
                    HasPile = ReleaseMutexed(StackList.Count - 2);
                }
            }

            if (!HasPile && !UpLayerHasMutex) //组互斥释放
            {
                //  GLog.Log("===UpStack group mutex up====" + table.name);
                if (index > 0 && index < UIPageManager.Ins.LayerArray.Length)
                {
                    UILayer layer;
                    for (int i = index - 1; i >= 0; i--)
                    {
                        layer = UIPageManager.Ins.LayerArray[i];
                        layer.UpLayerHasMutex = false;
                        if (!layer.uiStackTransform.gameObject.activeSelf)
                        {
                            layer.uiStackTransform.gameObject.SetActive(true);
                        }

                        if (layer.HasPile) break;
                    }
                }
            }
        }
    }
}